﻿using System;
using System.Linq;
using System.Reflection;
using log4net;
using YZAutoDWR.Entity;

namespace YZAutoDWR.Data;

public class ServiceTableInitializer
{
    private readonly DWRDbContext _dbContext;
    private static readonly ILog Log = LogManager.GetLogger(typeof(App));

    public ServiceTableInitializer(DWRDbContext dbContext)
    {
        _dbContext = dbContext;
    }

    public void InitializeServiceTable()
    {
        lock (DbContextLock.Locker)
        {
            // 获取所有继承了 BaseEntity 的业务 Entity 并进行初始化
            var entityTypes = Assembly.GetExecutingAssembly().GetTypes()
                .Where(t => t is { IsClass: true, IsAbstract: false } && t.IsSubclassOf(typeof(BaseEntity)))
                .ToList();

            foreach (var entityType in entityTypes)
            {
                try
                {
                    var method = typeof(ServiceTableInitializer)
                        .GetMethod(nameof(InitializeEntity), BindingFlags.NonPublic | BindingFlags.Instance)
                        ?.MakeGenericMethod(entityType);

                    method?.Invoke(this, null);
                }
                catch (Exception ex)
                {
                    Log.Error($"初始化 {entityType.Name} 表失败: " + ex);
                }
            }
        }
    }

    private void InitializeEntity<T>() where T : BaseEntity
    {
        var dbSet = _dbContext.Set<T>();
        if (dbSet.Any()) return;

        var instance = Activator.CreateInstance<T>();

        // 检查 Initialize 方法是否被重写, 重写了 Initialize 的 Entity 都插入初始数据
        var initializeMethod = typeof(T).GetMethod("Initialize");
        if (initializeMethod?.DeclaringType == typeof(BaseEntity)) return;
        instance.Initialize();
        dbSet.Add(instance);
        _dbContext.SaveChanges();

        Log.Info($"已初始化 {typeof(T).Name} 表数据");
    }

    private static class DbContextLock
    {
        public static readonly object Locker = new();
    }
}